package router

import (
	"encoding/json"
	"fmt"
	"gitee.com/zaper/patch/constant"
	"gitee.com/zaper/patch/database"
	"gitee.com/zaper/patch/middleware/http_middleware"
	"gitee.com/zaper/patch/service/hot_patch_client_service"
	"gitee.com/zaper/patch/servicecenter"
	"gitee.com/zaper/patch/util"
	"gitee.com/zaper/patch/versionmanager"
	"gitee.com/zaper/private-logger"
	"github.com/gin-gonic/gin"
	"io"
	"os"
)

var (
	Groups = make(map[string]string)
)

func init() {
	Groups["v1"] = "/api/v1/"
	Groups["v2"] = "/api/v2"
}

type OptionList = gin.HandlerFunc

type HttpRouter struct {
	Group    string
	Url      string
	FuncType string
	Func     []OptionList
}

func GetHttpMiddleWare() []gin.HandlerFunc {
	var handlers []gin.HandlerFunc
	handlers = append(handlers,
		http_middleware.ControllerLogFilter(),
		http_middleware.PrivilegeFilter(),
		http_middleware.OperationLog(),
	)
	return handlers
}

func GetRoute() []HttpRouter {
	return []HttpRouter{
		{Groups["v1"], "/hotpatch/getversion", constant.HttpGET,
			[]OptionList{getHotPatchVersion}},
		{Groups["v1"], "/services/instance", constant.HttpGET,
			[]OptionList{getServiceInfo}},
		{Groups["v2"], "/services/instance", constant.HttpGET,
			[]OptionList{getServiceInfo, getServiceInfoV2}},
		{Groups["v1"], "/file/create", constant.HttpPOST,
			[]OptionList{createRemoteFile}},
		{Groups["v1"], "push/file/info", constant.HttpPUT,
			[]OptionList{pushFileToRemote}},
		{Groups["v2"], "push/file/info", constant.HttpPUT,
			[]OptionList{pushFileToRemote, pushFileToRemoteV2}},
		{Groups["v1"], "/client/register", constant.HttpPOST,
			[]OptionList{ClientRegister}},
		{Groups["v1"], "/client/register/status", constant.HttpPOST,
			[]OptionList{ClientRegisterStatus}},
	}
}

func getHotPatchVersion(context *gin.Context) {
	logger.Infof("========================== %s", "GetHotPatchVersion")
	hotVersionMode := versionmanager.HotVersionMode{
		HotVersion:     "1.2.0",
		HotVersionType: "type0",
	}
	var hotVersionJson, err = json.Marshal(&hotVersionMode)
	response := hotVersionJson
	if err != nil {
		response = nil
	}
	util.HttpContextJSON(context, string(response))
}

func getServiceInfo(context *gin.Context) {
	logger.Infof("========================== %s", "GetServiceInfo")
	serviceInstance := servicecenter.ServiceInstance{
		Ip:   "127.0.0.1",
		Port: "8080",
	}
	util.HttpContextJSON(context, serviceInstance)
}

func getServiceInfoV2(context *gin.Context) {
	logger.Infof("========================== %s", "GetServiceInfoV2")
	util.HttpContextJSON(context, "GetServiceInfoV2")
}

func createRemoteFile(context *gin.Context) {
	request, err := io.ReadAll(context.Request.Body)
	logger.Infof("========================== %s", "CreateRemoteFile")
	if err != nil {
		logger.Infof("context.Request.Body is error, %s", err)
	}
	var rt = make(map[string]string)
	err1 := json.Unmarshal(request, &rt)
	if err1 != nil {
		logger.Infof("request unmarshal is error, %s", err1)
	}
	file, err2 := os.Create(rt["name"])
	if err2 != nil {
		logger.Infof("Create fail is error, %s", err2)
		rt["result"] = "false"
	} else {
		rt["result"] = "true"
		_ = file.Close()
	}

	logger.Infof("Response is ==================== %s", rt)
	util.HttpContextJSON(context, rt)
}

func pushFileToRemote(context *gin.Context) {
	logger.Infof("========================== %s", "PushFileToRemote")
	util.HttpContextJSON(context, "PushFileToRemote")
}

func pushFileToRemoteV2(context *gin.Context) {
	logger.Infof("========================== %s", "PushFileToRemoteV2")
	util.HttpContextJSON(context, "PushFileToRemoteV2")
}

func ClientRegister(context *gin.Context) {
	body, err := io.ReadAll(context.Request.Body)
	if err != nil {
		util.HttpContextJSON(context, fmt.Sprintf("read request body fail, errorcode is %d", 10001))
		return
	}
	clientMode := &hot_patch_client_service.HotPatchClientModel{}
	err = json.Unmarshal(body, clientMode)
	if err != nil {
		util.HttpContextJSON(context, fmt.Sprintf("read request body fail, errorcode is %d", 10005))
		return
	}
	dbManager := database.GetDataBaseManager()
	count, err := dbManager.QueryCountSql(database.SqlInfos["hot_patch_client_query_count"],
		clientMode.ProcessName)
	//格式化sql
	if count == 0 {
		err = dbManager.PrepareExecSql(database.SqlInfos["hot_patch_client_insert"], clientMode.ProcessName,
			clientMode.ProcessIp, clientMode.ProcessPort, clientMode.ProcessType, clientMode.DateTime)
	} else {
		err = dbManager.PrepareExecSql(database.SqlInfos["hot_patch_client_update"], clientMode.ProcessName,
			clientMode.ProcessIp, clientMode.ProcessPort, clientMode.ProcessType, clientMode.DateTime,
			clientMode.ProcessName)
	}
	// 入库
	if err != nil {
		util.HttpContextJSON(context, fmt.Sprintf("register fail, errorcode is %d", 10010))
		return
	}
	util.HttpContextJSON(context, util.NewHttpResponseError(0, "register success!!!"))
}

func ClientRegisterStatus(context *gin.Context) {
	body, err := io.ReadAll(context.Request.Body)
	if err != nil {
		util.HttpContextJSON(context, util.NewHttpResponseError(10001, "read request body fail"))
		return
	}
	//反序列化
	clientMode := &hot_patch_client_service.HotPatchClientModel{}
	err = json.Unmarshal(body, clientMode)
	if err != nil {
		util.HttpContextJSON(context, util.NewHttpResponseError(10005, "read request body fail"))
		return
	}
	// 查詢
	dbManager := database.GetDataBaseManager()
	count, err := dbManager.QueryCountSql(database.SqlInfos["hot_patch_client_query_count"],
		clientMode.ProcessName)
	if count != 1 || err != nil {
		util.HttpContextJSON(context, util.NewHttpResponseError(1, "process register fail"))
		return
	}
	util.HttpContextJSON(context, util.NewHttpResponseError(0, "check register status success"))
}
